﻿using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Colors;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using System.Collections.Generic;

namespace AutoCAD_CSharp_plug_in3.Chap03
{
    public static partial class LayerUtils
    {
        /// <summary>
        /// 获取图层，如果有该体图层则创建一个
        /// </summary>
        /// <param name="db"></param>
        /// <param name="layName"></param>
        /// <param name="colorIndex"></param>
        /// <returns></returns>
        public static ObjectId GetLayer(this Database db, string layName, int colorIndex)
        {
            db = db ?? HostApplicationServices.WorkingDatabase;
            LayerTable lt = (LayerTable)db.LayerTableId.GetObject(OpenMode.ForRead);
            if (!lt.Has(layName))
            {
                LayerTableRecord ltr = new LayerTableRecord();
                ltr.Name = layName;
                ltr.Color = Color.FromColorIndex(ColorMethod.ByAci, (short)colorIndex);
                lt.UpgradeOpen();
                lt.Add(ltr);
                db.TransactionManager.AddNewlyCreatedDBObject(ltr, true);
                lt.DowngradeOpen();
            }

            return lt[layName];
        }

        /// <summary>
        /// 根据名称获取图层ID
        /// </summary>
        /// <param name="db"></param>
        /// <param name="layName"></param>
        /// <returns></returns>
        public static ObjectId GetLayer(this Database db, string layName)
        {
            db = db ?? HostApplicationServices.WorkingDatabase;
            LayerTable lt = (LayerTable)db.LayerTableId.GetObject(OpenMode.ForRead);
            if (!lt.Has(layName))
            {
                LayerTableRecord ltr = new LayerTableRecord();
                ltr.Name = layName;
                lt.UpgradeOpen();
                lt.Add(ltr);
                db.TransactionManager.AddNewlyCreatedDBObject(ltr, true);
                lt.DowngradeOpen();
            }

            return lt[layName];
        }

        /// <summary>
        /// 关闭图层
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="LayerName">图层名</param>
        /// <returns>bool</returns>
        public static bool HideLayer(this Database db, string LayerName)
        {
            bool isOk = true;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                DocumentLock m_DocumentLock = Application.DocumentManager.MdiActiveDocument.LockDocument();
                //打开层表
                LayerTable lt = (LayerTable)trans.GetObject(db.LayerTableId, OpenMode.ForRead);
                //判断指定的图形名是否存在
                if (lt.Has(LayerName))
                {
                    LayerTableRecord ltr = (LayerTableRecord)lt[LayerName].GetObject(OpenMode.ForWrite);
                    if (!ltr.IsOff)
                    {
                        ltr.IsOff = true;
                    }

                    //ltr.IsHidden = true;
                    trans.Commit();
                }
                else
                {
                    isOk = false;
                }

                m_DocumentLock.Dispose();
            }

            return isOk;
        }

        /// <summary>
        /// 打开图层
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="LayerName">图层名</param>
        /// <returns>bool</returns>
        public static bool ShowLayer(this Database db, string LayerName)
        {
            bool isOk = true;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                DocumentLock m_DocumentLock = Application.DocumentManager.MdiActiveDocument.LockDocument();
                //打开层表
                LayerTable lt = (LayerTable)trans.GetObject(db.LayerTableId, OpenMode.ForRead);
                //判断指定的图形名是否存在
                if (lt.Has(LayerName))
                {
                    LayerTableRecord ltr = (LayerTableRecord)lt[LayerName].GetObject(OpenMode.ForWrite);
                    if (ltr.IsOff)
                    {
                        ltr.IsOff = false;
                    }

                    trans.Commit();
                }
                else
                {
                    isOk = false;
                }

                m_DocumentLock.Dispose();
            }

            return isOk;
        }

        /// <summary>
        /// 打开图层
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="LayerName">图层名</param>
        /// <returns>bool</returns>
        public static bool ShowLayers(this Database db, string[] LayerNames)
        {
            bool isOk = true;
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                DocumentLock m_DocumentLock = Application.DocumentManager.MdiActiveDocument.LockDocument();
                //打开层表
                LayerTable lt = (LayerTable)trans.GetObject(db.LayerTableId, OpenMode.ForRead);
                //判断指定的图形名是否存在
                foreach (string LayerName in LayerNames)
                {
                    if (lt.Has(LayerName))
                    {
                        LayerTableRecord ltr = (LayerTableRecord)lt[LayerName].GetObject(OpenMode.ForWrite);
                        if (ltr.IsOff)
                        {
                            ltr.IsOff = false;
                            ed.WriteMessage("\n" + LayerName + " 图层显示！\n");
                        }
                    }
                    else
                    {
                        isOk = false;
                    }
                }

                trans.Commit();
                m_DocumentLock.Dispose();
                ed.Regen();
            }

            return isOk;
        }

        /// <summary>
        /// 隐藏图层
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="LayerName">图层名</param>
        /// <returns>bool</returns>
        public static bool HideLayers(this Database db, string[] LayerNames)
        {
            bool isOk = true;
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                DocumentLock m_DocumentLock = Application.DocumentManager.MdiActiveDocument.LockDocument();
                //打开层表
                LayerTable lt = (LayerTable)trans.GetObject(db.LayerTableId, OpenMode.ForRead);
                //判断指定的图形名是否存在
                foreach (string LayerName in LayerNames)
                {
                    if (lt.Has(LayerName))
                    {
                        LayerTableRecord ltr = (LayerTableRecord)lt[LayerName].GetObject(OpenMode.ForWrite);
                        if (!ltr.IsOff)
                        {
                            ltr.IsOff = true;
                            ed.WriteMessage("\n" + LayerName + " 图层隐藏！\n");
                        }
                    }
                    else
                    {
                        isOk = false;
                    }
                }

                trans.Commit();
                m_DocumentLock.Dispose();
                ed.Regen();
            }

            return isOk;
        }


        /// <summary>
        /// 切换图层
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="LayerName">图层名</param>
        /// <returns>bool</returns>
        public static bool SwitchLayerHideShow(this Database db, string LayerName)
        {
            bool isOk = true;
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                DocumentLock m_DocumentLock = Application.DocumentManager.MdiActiveDocument.LockDocument();
                //打开层表
                LayerTable lt = (LayerTable)trans.GetObject(db.LayerTableId, OpenMode.ForRead);
                //判断指定的图形名是否存在
                if (lt.Has(LayerName))
                {
                    LayerTableRecord ltr = (LayerTableRecord)lt[LayerName].GetObject(OpenMode.ForWrite);
                    if (ltr.IsOff)
                    {
                        ltr.IsOff = false;
                        ed.WriteMessage("\n" + LayerName + " 图层显示！\n");
                    }
                    else
                    {
                        ltr.IsOff = true;
                        ed.WriteMessage("\n" + LayerName + " 图层隐藏！\n");
                    }

                    trans.Commit();
                    ed.Regen();
                }
                else
                {
                    isOk = false;
                }

                m_DocumentLock.Dispose();
            }

            return isOk;
        }

        /// <summary>
        /// 锁定图层
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="LayerName">图层名</param>
        /// <returns>bool</returns>
        public static bool LockLayer(this Database db, string LayerName)
        {
            bool isOk = true;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                //打开层表
                LayerTable lt = (LayerTable)trans.GetObject(db.LayerTableId, OpenMode.ForRead);
                //判断指定的图形名是否存在
                if (lt.Has(LayerName))
                {
                    LayerTableRecord ltr = (LayerTableRecord)lt[LayerName].GetObject(OpenMode.ForWrite);
                    ltr.IsLocked = true;
                    trans.Commit();
                }
                else
                {
                    isOk = false;
                }
            }

            return isOk;
        }


        /// <summary>
        /// 解除锁定图层
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="LayerName">图层名</param>
        /// <returns>bool</returns>
        public static bool UnLockLayer(this Database db, string LayerName)
        {
            bool isOk = true;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                //打开层表
                LayerTable lt = (LayerTable)trans.GetObject(db.LayerTableId, OpenMode.ForRead);
                //判断指定的图形名是否存在
                if (lt.Has(LayerName))
                {
                    LayerTableRecord ltr = (LayerTableRecord)lt[LayerName].GetObject(OpenMode.ForWrite);
                    ltr.IsLocked = false;
                    trans.Commit();
                }
                else
                {
                    isOk = false;
                }
            }

            return isOk;
        }


        /// <summary>
        /// 设置当前图层
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="LayerName">图层名</param>
        /// <returns>bool</returns>
        public static bool SetCurrentLayer(this Database db, string LayerName)
        {
            bool isSetOk = false;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                //打开层表
                LayerTable lt = (LayerTable)trans.GetObject(db.LayerTableId, OpenMode.ForRead);
                //判断要设置的图层名是否存在
                if (lt.Has(LayerName))
                {
                    //获取指定图层名的ObjectId
                    ObjectId layerId = lt[LayerName];
                    //判断要设置的图形是否已是当前图层
                    if (db.Clayer != layerId)
                    {
                        db.Clayer = layerId;
                    }

                    isSetOk = true;
                }

                trans.Commit();
            }

            return isSetOk;
        }


        /// <summary>
        /// 返回所有层表记录
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <returns>List<LayerTableRecord></returns>
        public static List<LayerTableRecord> GetAllLayers(this Database db)
        {
            List<LayerTableRecord> layerList = new List<LayerTableRecord>();
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                //打开层表
                LayerTable lt = (LayerTable)trans.GetObject(db.LayerTableId, OpenMode.ForRead);
                lt.GenerateUsageData();
                foreach (ObjectId item in lt)
                {
                    LayerTableRecord ltr = (LayerTableRecord)item.GetObject(OpenMode.ForRead);
                    layerList.Add(ltr);
                }
            }

            return layerList;
        }


        /// <summary>
        /// 获取所有图层名
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <returns>List<string></returns>
        public static List<string> GetAllLayersName(this Database db)
        {
            List<string> layerNamesList = new List<string>();
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                //打开层表
                LayerTable lt = (LayerTable)trans.GetObject(db.LayerTableId, OpenMode.ForRead);
                foreach (ObjectId item in lt)
                {
                    LayerTableRecord ltr = (LayerTableRecord)item.GetObject(OpenMode.ForRead);
                    layerNamesList.Add(ltr.Name);
                }
            }

            return layerNamesList;
        }

        /// <summary>
        /// 删除图层
        /// </summary>
        /// <param name="db">图形数据库</param>
        /// <param name="layerName">图层名</param>
        /// <returns>bool</returns>
        public static bool DeleteLayer(this Database db, string layerName)
        {
            if (layerName == "0" || layerName == "Defpoints") return false;
            bool isDeleteOK = false;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                LayerTable lt = (LayerTable)trans.GetObject(db.LayerTableId, OpenMode.ForRead);
                lt.GenerateUsageData();
                //判断要删除的图层名是否存在
                if (lt.Has(layerName))
                {
                    LayerTableRecord ltr = (LayerTableRecord)lt[layerName].GetObject(OpenMode.ForWrite);
                    if (!ltr.IsUsed && db.Clayer != lt[layerName])
                    {
                        ltr.Erase();
                        isDeleteOK = true;
                    }
                }
                else
                {
                    isDeleteOK = true;
                }

                trans.Commit();
            }

            return isDeleteOK;
        }


        /// <summary>
        /// 删除所有未使用的图层
        /// </summary>
        /// <param name="db"></param>
        public static void DeleteNotUsedLayer(this Database db)
        {
            db = db ?? HostApplicationServices.WorkingDatabase;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                LayerTable lt = (LayerTable)trans.GetObject(db.LayerTableId, OpenMode.ForRead);
                lt.GenerateUsageData();
                foreach (ObjectId item in lt)
                {
                    LayerTableRecord ltr = (LayerTableRecord)item.GetObject(OpenMode.ForWrite);
                    if (!ltr.IsUsed)
                    {
                        ltr.Erase();
                    }
                }

                trans.Commit();
            }
        }
    }
}